from structures.basic_structure import BasicStructure
from trajectories.traj_b_spline_curve import BSplineCurveTrajectory
from trajectories.traj_base import BaseTrajectory
from trajectories.traj_circle import CircleTrajectory
from trajectories.traj_forward import ForwardTrajectory
from trajectories.traj_free_drawing import FreeDrawingTrajectory
from trajectories.traj_line import LineTrajectory
from trajectories.traj_rect import RectTrajectory
from trajectories.traj_triangle import TriangleTrajectory
from trajectories.traj_walks import WalksTrajectory


class TrajectoryFactory:

    def __init__(self, ls: BasicStructure):
        self._ls: BasicStructure = ls
        self.all_tracks = {
            WalksTrajectory.TRACK_KEY: lambda: WalksTrajectory(),
            LineTrajectory.TRACK_KEY: lambda: LineTrajectory(),
            CircleTrajectory.TRACK_KEY: lambda: CircleTrajectory(),
            RectTrajectory.TRACK_KEY: lambda: RectTrajectory(),
            TriangleTrajectory.TRACK_KEY: lambda: TriangleTrajectory(),
            FreeDrawingTrajectory.TRACK_KEY: lambda: FreeDrawingTrajectory(),
            BSplineCurveTrajectory.TRACK_KEY: lambda: BSplineCurveTrajectory(),
            ForwardTrajectory.TRACK_KEY: lambda: ForwardTrajectory(),
        }

    def __new_trajectory(self, track_key):
        return self.all_tracks[track_key]()

    def generate(self, track_key, update_cb=None, *args):
        if track_key == WalksTrajectory.TRACK_KEY:
            trajectory = self._ls.get_walks_trajectory()
            if trajectory is not None and trajectory.is_running:
                trajectory.is_running = False
                self._ls.set_walks_trajectory(None)
                return

        traj: BaseTrajectory = self.__new_trajectory(track_key)
        if traj is None:
            return

        traj.init_args(args)

        if traj is FreeDrawingTrajectory:
            # 自由绘制的轨迹不需要在创建的时候运行
            return traj

        traj.run(update_cb, self._ls)
        traj.save(self._ls)

        return traj

    def clean(self, track_key):
        if track_key == WalksTrajectory.TRACK_KEY:
            self._ls.set_walks_trajectory(None)
            return True

        trajectory_list = self._ls.get_trajectory_list()
        if len(trajectory_list) > 0:
            traj: BaseTrajectory = trajectory_list.pop()
            traj.is_running = False
            return True

        return False

    def is_any_trajectory_running(self):
        trajectory_list = self._ls.get_trajectory_list()
        return any(traj.is_running for traj in trajectory_list)
